<?php

namespace App\Service\OpenShop;

use AlibabaCloud\SDK\Dyvmsapi\V20170525\Models\GetCallInfoResponseBody\data;
use App\Enums\OpenShop\InvestmentPromotion\UserContractEnum;
use App\Http\Resources\OpenShop\InvestmentPromotion\ContractTemplateListResource;
use App\Library\FeiShu\SendFs;
use App\Models\Common\ConfigModel;
use App\Models\Kms\User\KmsUser;
use App\Models\OpenShop\InvestmentPromotion\OpenShopContractTemplateLogModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopContractTemplateModel;
use App\Remote\Feishu\Departments\DepartmentsRemote;
use App\Remote\Rms\RmsUserRemote;
use App\Service\BaseService;
use App\Service\OpenShop\Feishu\FeishuApiService;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
use Illuminate\Validation\ValidationException;
use Kuafu\GeneralFs\BuildFs;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

class ContractTemplateService extends BaseService
{

    /**
     * @throws GuzzleException
     */
    public static function dataList($contractType, $mode, $templateName, $pageSize, $pageNum): array
    {

        $paginator = OpenShopContractTemplateModel::query()
                                                  ->when($contractType, function ($query) use ($contractType) {
                                                      return $query->whereJsonContains('contractTypeV2', [$contractType]);
                                                  })
                                                  ->when($mode, function ($query) use ($mode) {
                                                      return $query->where("mode", $mode);
                                                  })
                                                  ->when($templateName, function ($query) use ($templateName) {
                                                      return $query->where("templateName", 'like',
                                                          "%" . $templateName . "%");
                                                  })
                                                  ->orderBy(
                                                      "id",
                                                      "desc"
                                                  )->paginate($pageSize,
                [
                    'id',
                    "templateName",
                    'mode',
                    'shopCount',
                    'startTime',
                    'endTime',
                    'createdByUid',
                    'contractType',
                    'isShow',
                    'contractTypeV2'
                ], 'page', $pageNum);

        //分组统计
        $mergeList = OpenShopContractTemplateModel::query()
                                                  ->select('isShow', DB::raw('count(id) as num'))
                                                  ->groupBy("isShow")
                                                  ->get()
                                                  ->toArray();

        $totalNum = OpenShopContractTemplateModel::query()->count();
        $newIsShowData[] = [
            'isShowText' => "全部",
            'num'        => $totalNum,
        ];
        $isShowTextList  = OpenShopContractTemplateModel::IS_SHOW_TEXT;
        foreach ($isShowTextList as $isShow => $isShowText) {
            $num = 0;
            if (!empty($mergeList)) {
                foreach ($mergeList as $v) {
                    if ($isShow == $v['isShow']) {
                        $num = $v['num'];
                        break;
                    }
                }
            }
            $newIsShowData[] = [
                'isShowText' => $isShowText,
                'num'        => $num,
            ];
        }

        $dataList = $paginator->items();
        if (!empty($dataList)) {
            $userIdList = array_unique(array_column($dataList, 'createdByUid'));
            $userIdList = array_values($userIdList);
            if (count($userIdList) == 1 && $userIdList[0] == 0) {
                $userInfo = [];
            } else {
                $userInfo = collect(RmsUserRemote::getRmsUserByIds(array_unique($userIdList),
                    ['id', 'username']))->keyBy('id');
            }

            foreach ($dataList as $k => $v) {
                $createUserName = "飞书";
                if ($v['createdByUid'] > 0 && !is_null($v['createdByUid'])) {
                    $createUserName = $userInfo[$v['createdByUid']]['username']?? '--';;
                }
                $dataList[$k]['createUserText']   = $createUserName;
                $dataList[$k]['modeText']         = OpenShopContractTemplateModel::MODE_MAP_TEXT[$v['mode']] ?? '未知';
                $dataList[$k]['isShowText']       = OpenShopContractTemplateModel::IS_SHOW_TEXT[$v['isShow']] ?? '未知';
                $dataList[$k]['startTime']        = date("Y-m-d H:i:s", $v['startTime']);
                $dataList[$k]['endTime']          = date("Y-m-d H:i:s", $v['endTime']);

                // v2
                $contractTypeV2Data = [];
                if(!is_null($v['contractTypeV2'])){
                    $contractTypeV2 = json_decode($v['contractTypeV2'])??[];
                    if(!empty($contractTypeV2)){
                        for ($i=0;$i<count($contractTypeV2);$i++){
                            $contractTypeV2Data[] = UserContractEnum::CONTRACT_TYPE[$contractTypeV2[$i]] ?? '未知';
                        }
                    }
                }
                $dataList[$k]['contractTypeText'] = implode(',',$contractTypeV2Data);

            }
        }

        return [
            'count'     => (int)$paginator->total(),
            'pageNum'   => (int)$pageNum,
            'pageSize'  => (int)$pageSize,
            'mergeList' => $newIsShowData,
            'list'      => $dataList
        ];

    }


    /**
     * @throws GuzzleException
     */
    public static function info(int $id): array
    {
        $info = OpenShopContractTemplateModel::query()->where("id", $id)->first();
        if (empty($info)) {
            return self::returnData(400,'数据不存在');
        }
        $info = $info->toArray();

        $createUserName = "飞书";
        if ($info['createdByUid'] > 0 && !is_null($info['createdByUid'])) {
            $userInfo   = collect(RmsUserRemote::getRmsUserByIds([$info['createdByUid']],['id', 'username']))->keyBy('id');
            $createUserName = $userInfo[$info['createdByUid']]['username']?? '--';;
        }

        $info['createUserText']   = $createUserName;
        $info['modeText']         = OpenShopContractTemplateModel::MODE_MAP_TEXT[$info['mode']] ?? '未知';
        $info['isShowText']       = OpenShopContractTemplateModel::IS_SHOW_TEXT[$info['isShow']] ?? '未知';
        $info['startTime']        = date("Y-m-d H:i:s", $info['startTime']);
        $info['endTime']          = date("Y-m-d H:i:s", $info['endTime']);

        // v2
        $contractTypeV2Data = [];
        if(!is_null($info['contractTypeV2'])){
            $contractTypeV2 = json_decode($info['contractTypeV2'])??[];
            if(!empty($contractTypeV2)){
                for ($i=0;$i<count($contractTypeV2);$i++){
                    $contractTypeV2Data[] = UserContractEnum::CONTRACT_TYPE[$contractTypeV2[$i]] ?? '未知';
                }
            }
        }
        $info['contractTypeText'] = implode(',',$contractTypeV2Data);

        unset($info['createdAt']);
        unset($info['createdByUid']);
        unset($info['updatedAt']);
        unset($info['updatedByUid']);

        $logList = OpenShopContractTemplateLogModel::query()
                                                   ->select("id", 'title', 'remark','createdAt', 'createdByUid')
                                                   ->where('contractTemplateId', $id)
                                                   ->get()
                                                   ->toArray();
        if (!empty($logList)) {
            $userIdList = array_unique(array_column($logList, 'createdByUid'));
            $userIdList = array_values($userIdList);
            if (count($userIdList) == 1 && $userIdList[0] == 0) {
                $userInfo = [];
            } else {
                $userInfo = collect(RmsUserRemote::getRmsUserByIds(array_unique($userIdList),
                    ['id', 'username']))->keyBy('id');
            }

            foreach ($logList as $k => $item) {
                $logList[$k]['createdAt'] = date("Y-m-d H:i:s",strtotime($item['createdAt']));

                $createUserName = "--";
                if ($item['createdByUid'] > 0 && !is_null($item['createdByUid'])) {
                    $createUserName = $userInfo[$item['createdByUid']]['username']?? '--';;
                }
                $logList[$k]['createdUidName'] = $createUserName;
            }
        }

        return self::returnData(200,'ok',['info' => $info, 'logList' => $logList]);

    }


    public static function updateShow(int $id, int $isShow, int $userId): array
    {

        $isShowIdList = array_keys(OpenShopContractTemplateModel::IS_SHOW_TEXT);
        if (!in_array($isShow, $isShowIdList)) {
            return self::returnData(400,'isShow不合法');
        }

        $info = OpenShopContractTemplateModel::query()->where("id", $id)->first();
        if (empty($info)) {
            return self::returnData(400,'数据不存在');
        }

        if ($info->isShow == OpenShopContractTemplateModel::IS_SHOW_3) {
            return self::returnData(400,'已关闭不允许操作');
        }

        if ($info->isShow == $isShow) {
            return self::returnData(400,'状态未做改变');
        }

        $isShowTextOld = OpenShopContractTemplateModel::IS_SHOW_TEXT[$info->isShow];
        $isShowText    = OpenShopContractTemplateModel::IS_SHOW_TEXT[$isShow];

        DB::beginTransaction();
        try {

            OpenShopContractTemplateModel::query()->where("id", $id)->update([
                'updatedAt'    => time(),
                'updatedByUid' => $userId,
                'isShow'       => $isShow
            ]);

            OpenShopContractTemplateLogModel::query()->insert([
                'title'              => $isShowText,
                'remark'             => $isShowTextOld . '=>' . $isShowText,
                'contractTemplateId' => $id,
                'createdAt'          => time(),
                'createdByUid'       => $userId,
            ]);

            DB::commit();
        } catch (\Exception $exception) {
            DB::rollback();
            return self::returnData(400,$exception->getMessage());
        }

        return self::returnData(200,'ok');

    }


    /**
     * @throws GuzzleException
     * @throws ValidationException
     */
    public static function feiShuCallback(string $appid, string $instancesId): array
    {
        // 查询一次详情
        $instancesIdInfo = ContractTemplateFeiShuService::getInstancesIdData($appid,$instancesId);
        if (empty($instancesIdInfo) || empty($instancesIdInfo['task_list'])) {
            return self::returnData(400, "数据错误", []);
        }

        // 检测是否审批完成
        $task_list  = $instancesIdInfo['task_list'];
        $successNum = 0;
        foreach ($task_list as $key => $value) {
            if ($value['status'] == 'APPROVED') {
                $successNum++;
            }
        }
        if ($successNum < count($task_list)) {
            return self::returnData(400, "请先等待审批完成", []);
        }

        // 重复处理检测
        $cacheExKey = 'feiShu:callback:contractTemplate:deal:' . $instancesId;
        $isDeal = Cache::get($cacheExKey, 0);
        if ($isDeal == 1) {
            return self::returnData(400, "已处理过，无需处理", []);
        }

        // form表单处理
        $formData = json_decode($instancesIdInfo['form'], true) ?? [];
        if (empty($formData)) {
            return self::returnData(400, "审批数据解析失败", []);
        }

        $insertData = [];
        $cardData = [];
        foreach ($formData as $k => $item) {
            $value = $item['value'];

            switch ($item['id']) {
                case ContractTemplateFeiShuService::FORM_DATA_ID_NAME:

                    // 政策名称
                    $insertData['templateName'] = $value;
                    break;

                case ContractTemplateFeiShuService::FORM_DATA_ID_TIME_START_END:

                    // 起始时间
                    $insertData['startTime'] = strtotime($value['start']);
                    $insertData['endTime']   = strtotime($value['end']);
                    break;

                case ContractTemplateFeiShuService::FORM_DATA_ID_CONTRACT_TYPE:

                    // 签约类型： 多个文本值，需要转换成ID
                    $contractTypeStr        = $value;
                    $contractTypeArr        = [];
                    $oldContractType        = 1;
                    $contractTypeConfigList = UserContractEnum::CONTRACT_TYPE;
                    foreach ($contractTypeConfigList as $contractTypeId => $contractTypeName) {
                        for ($i = 0; $i < count($contractTypeStr); $i++) {
                            if ($contractTypeStr[$i] == $contractTypeName) {

                                $oldContractType = $contractTypeId;

                                $contractTypeArr[] = $contractTypeId;
                                break;
                            }
                        }
                    }
                    // V2
                    $insertData['contractTypeV2'] = json_encode($contractTypeArr);

                    // 老字段，临时使用最后一个值
                    $insertData['contractType'] = $oldContractType;

                    //卡片消息使用
                    $cardData['fsCardContractTypeStr'] = $contractTypeStr;

                    break;

                case ContractTemplateFeiShuService::FORM_DATA_ID_SHOP_COUNT:

                    // 门店数量
                    $insertData['shopCount'] = $value;
                    break;

                case ContractTemplateFeiShuService::FORM_DATA_ID_MODE:

                    // 加盟模式: 文本值，需要转换成ID
                    $modeName       = $value;
                    $modeId         = 1;
                    $modeConfigList = OpenShopContractTemplateModel::MODE_MAP_TEXT;
                    foreach ($modeConfigList as $id => $text) {
                        if ($modeName == $text) {
                            $modeId = $id;
                            break;
                        }
                    }
                    $insertData['mode'] = $modeId;
                    break;

                case ContractTemplateFeiShuService::FORM_DATA_ID_DEPOSIT:

                    // 保证金： 元 转换成分
                    $insertData['deposit'] = $value * 100;
                    break;

                case ContractTemplateFeiShuService::FORM_DATA_ID_DEPOSIT_AMOUNT:

                    // 定金模式： 定金金额 元 转换成分
                    $insertData['depositAmount'] = $value * 100;
                    break;

                case ContractTemplateFeiShuService::FORM_DATA_ID_INITIAL_FEE:

                    // 品牌使用费 == 加盟费 元 转换成分
                    $insertData['initialFee'] = $value * 100;
                    break;

                case ContractTemplateFeiShuService::FORM_DATA_ID_TECHNOLOGY_TRANSFER_FEE:

                    // 经营技术授予费(元) == 技术转让费 元 转换成分
                    $insertData['technologyTransferFee'] = $value * 100;
                    break;

                case ContractTemplateFeiShuService::FORM_DATA_ID_GUIDANCE_FEE:

                    // 咨询指导服务费==品牌指导费 元 转换成分
                    $insertData['guidanceFee'] = $value * 100;
                    break;

                case ContractTemplateFeiShuService::FORM_DATA_ID_MANAGEMENT_COST:

                    // 传统模式：特权使用费(管理费)第一年(元) 元 转换成分
                    $insertData['managementCost'] = $value * 100;
                    break;

                case ContractTemplateFeiShuService::FORM_DATA_ID_MANAGEMENT_COST_EVERY_YEAR:

                    // 传统模式：特权使用费(管理费)每年(元) 元 转换成分
                    $insertData['managementCostEveryYear'] = $value * 100;
                    break;

                case ContractTemplateFeiShuService::FORM_DATA_ID_DECORATION_DEPOSIT:

                    // 传统模式：装修保证金 元 转换成分
                    $insertData['decorationDeposit'] = $value * 100;
                    break;

                case ContractTemplateFeiShuService::FORM_DATA_ID_DEPOSIT_AMOUNT_RATIO:

                    // 分账模式：每月实收抽佣比例: 1%
                    $depositAmountRatio               = str_replace("%", '', $value) / 100;
                    $insertData['depositAmountRatio'] = sprintf("%.2f", $depositAmountRatio);

                    // 卡片消息
                    $cardData["fsCardDepositAmountRatio"] = $value;

                    break;

                case ContractTemplateFeiShuService::FORM_DATA_ID_MONTH_REAL_AMOUNT_COMMISSION_CAPPING:

                    // 分账模式：月实收抽佣封顶金额 元 转换成分
                    $insertData['monthRealAmountCommissionCapping'] = $value * 100;
                    break;

                case ContractTemplateFeiShuService::FORM_DATA_ID_AMOUNT_COMMISSION_CAPPING:
                    // 分账模式：是否抽佣累计封顶
                    $isCommissionCapping = 0;
                    if ($value > 0) {
                        $isCommissionCapping = 1;
                    }
                    $insertData['isCommissionCapping'] = $isCommissionCapping;

                    // 分账模式：抽佣累计封顶金额 元 转换成分
                    $insertData['amountCommissionCapping'] = $value * 100;
                    break;

            }

        }

        // 固定三年
        $insertData['year']         = 3;
        $insertData['createdAt']    = time();
        $insertData['createdByUid'] = 0;
        $insertData['version']      = 2; // 合同版本号

        // 特殊处理： 分账模式处理
        if ($insertData['mode'] == OpenShopContractTemplateModel::MODE_2){
            // 分账模式签约 contractType 固定用9
            $insertData['contractType'] = UserContractEnum::CONTRACT_TYPE_9;

            // 月实收抽佣封顶金额：分
            if ($insertData['depositAmountRatio'] != 0){
                $insertData['monthRealAmountCommissionCapping'] = sprintf("%.2f", ($insertData['monthRealAmountCommissionCapping']/100) / $insertData['depositAmountRatio'])  * 100 ;
            }
        }

        // 环境检测 : 包含qa & 非测试环境， 不执行
        if (strpos(strtolower($insertData['templateName']), 'qa') !== false && !in_array(config('app.env'),['qa','dev']) ) {
            return self::returnData(400,"qa数据禁止在生产环境执,名称：".$insertData['templateName'],[]);
        }

        // 环境检测 : 不含qa & 测试环境， 不执行
        if (strpos(strtolower($insertData['templateName']), 'qa') === false &&  in_array(config('app.env'),['qa','dev']) ) {
            return self::returnData(400,"生产数据禁止在qa环境执行,名称：".$insertData['templateName'],[]);
        }

        // 加锁
        Cache::put($cacheExKey, 1, 86400 * 2);

        // 合同名称检测 - 不可重复
        $infoByName = OpenShopContractTemplateModel::query()->where('templateName',$insertData['templateName'])->first();
        if(!is_null($infoByName)){
            // 推送卡片消息
            $card = [
                "header"   => [
                    "title" => [
                        "tag"     => "plain_text",
                        "content" => '新的加盟政策创建失败 - 名称重复'
                    ]
                ],
                'elements' => [
                    [
                        "tag"     => "markdown",
                        "content" => "名称：" . $insertData['templateName']
                    ]
                ],
            ];
            BuildFs::newRobot(SendFs::ROBOT_BUSINESS_CONTRACRT_TEMPLATE, BuildFs::MSG_TYPE_CARD)
                   ->setCardContent($card)
                   ->send();

            return self::returnData(400,"名称重复",[]);
        }

        $templateId = OpenShopContractTemplateModel::query()->insertGetId($insertData);
        if($templateId){

            // 推送卡片消息
            $card = ContractTemplateFeiShuService::dealFeiShuCardMsgContent($insertData,$cardData);
            BuildFs::newRobot(SendFs::ROBOT_BUSINESS_CONTRACRT_TEMPLATE, BuildFs::MSG_TYPE_CARD)
                   ->setCardContent($card)
                   ->send();

            return self::returnData(200,"ok",$insertData);
        }
        return self::returnData(400,"创建失败",[]);
    }

    /**
     * @throws GuzzleException
     * @throws ValidationException
     */
    public static function getFeiShuCallbackInfo(string $appId, string $instancesId)
    {
        return ContractTemplateFeiShuService::getInstancesIdData($appId, $instancesId);
    }


    /**
     *  更新加盟政策的状态
     */
    public static function updateStatus(): bool
    {
        // 启用中和未启用
        $dataList = OpenShopContractTemplateModel::query()
                                                 ->whereIn('isShow', [
                                                     OpenShopContractTemplateModel::IS_SHOW_1,
                                                     OpenShopContractTemplateModel::IS_SHOW_2
                                                 ])
                                                 ->get()
                                                 ->toArray();

        if (empty($dataList)) {
            return false;
        }

        $id_1    = []; // 需要改为 关闭的
        $id_2    = []; // 需要改为 开启的
        $id_3    = []; // 需要改为 未开启的
        $nowTime = time();
        foreach ($dataList as $k=>$value){
            if ($value['isShow'] == OpenShopContractTemplateModel::IS_SHOW_1){
                // 启用中已过期的关闭 或者 时间设置错误的关闭
                if ($value['endTime'] < $nowTime || $value['endTime'] < $value['startTime']) {
                    $id_1[] = $value['id'];
                }

                // 启用中 但是时间未到，改为 未启用
                if ($value['startTime'] > $nowTime) {
                    $id_3[] = $value['id'];
                }

            }

            if ($value['isShow'] == OpenShopContractTemplateModel::IS_SHOW_2) {
                // 未启用的到时间 自动开启
                if ($value['startTime'] < $nowTime && $value['endTime'] > $nowTime) {
                    $id_2[] = $value['id'];
                }
            }
        }

        if (!empty($id_1)) {
            OpenShopContractTemplateModel::query()->whereIn('id', $id_1)
                                         ->update([
                                             'isShow' => OpenShopContractTemplateModel::IS_SHOW_3,
                                         ]);
        }

        if (!empty($id_2)) {
            OpenShopContractTemplateModel::query()->whereIn('id', $id_2)
                                         ->update([
                                             'isShow' => OpenShopContractTemplateModel::IS_SHOW_1,
                                         ]);
        }

        if (!empty($id_3)) {
            OpenShopContractTemplateModel::query()->whereIn('id', $id_3)
                                         ->update([
                                             'isShow' => OpenShopContractTemplateModel::IS_SHOW_2,
                                         ]);
        }


        return true;

    }

}